home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 105 (1991-02)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 105 (1991-02)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / AmigaUUCP / uucico / uucico.c.old < prev    next >
Text File  |  1991-02-10  |  36KB  |  1,596 lines

  1.  
  2. /*
  3.  *  UUCICO.C
  4.  *
  5.  *  $Header: Beta:src/uucp/src/uucico/RCS/uucico.c,v 1.1 90/02/02 11:56:01 dillon Exp Locker: dillon $
  6.  *
  7.  *  (C) Copyright 1987 by John Gilmore.
  8.  *  Copying and use of this program are controlled by the terms of the Free
  9.  *  Software Foundation's GNU Emacs General Public License.
  10.  *
  11.  *  Derived from:
  12.  *  i[$]uuslave.c     1.7 08/12/85 14:04:20
  13.  *  which came from the ACGNJ BBS system at +1 201 753 9758.  Original
  14.  *  author unknown.
  15.  *
  16.  *  Ported to Amiga by William Loftus
  17.  *  Amiga Changes Copyright 1988 by William Loftus.  All rights reserved.
  18.  *  Additional Major Changes (c)Copyright 1989 by Matthew Dillon, All rights reserved
  19.  *
  20.  * 14-Oct-89, moved modem_init() to before poll_sys.
  21.  *
  22.  * -r option       (-r1 does a call out to all systems we have mail for)
  23.  * -D[EVICE] dev    sets serial device name (automatic from Getty)
  24.  * -U[NIT] unit     sets unit name (automatic from Getty)
  25.  * -h0            Ignore CD (carrier detect)
  26.  * -7
  27.  */
  28.  
  29.  
  30. #include "includes.h"           /* System include files, system dependent */
  31. #include "uucp.h"               /* Uucp definitions and parameters */
  32. #include <log.h>
  33. #include "version.h"
  34.  
  35. #define PROTOF_SHEREEQUALS  0x0001  /*    ProtoHacks  */
  36.  
  37. Prototype   int getname(int);
  38. Prototype   int get_proto(void);
  39. Prototype   int instr(char *, int, int);
  40. Prototype   int twrite(const char *, int);
  41. Prototype   void xlat_str(char *);
  42. Prototype   int read_ctl(void);
  43. Prototype   int do_outbound(void);
  44. Prototype   int call_system(char *, int);
  45. Prototype   int call_sysline(char *);
  46. Prototype   int do_session(int);
  47. Prototype   int top_level(int);
  48. Prototype   int do_one_slave(void);
  49. Prototype   int do_one_master(void);
  50. Prototype   int yesno(char, int, int);
  51. Prototype   int host_send_file(char *);
  52. Prototype   int host_receive_file(char *);
  53. Prototype   int local_send_file(char *, int *);
  54. Prototype   int local_receive_file(void);
  55. Prototype   int receive_file(FILE *, char *, char *, char *, int);
  56. Prototype   int send_file(FILE *);
  57.  
  58. Prototype   short ProtoHacks;
  59. Prototype   short PriMode;
  60. Prototype   short OldPri;
  61. Prototype   short IgnoreDTR;
  62. Prototype   int   PacketTimeout;
  63.  
  64. #define MAX_FLAGS    40
  65.  
  66. extern int errno;
  67.  
  68. IDENT(".15");
  69.  
  70. static char *Copyright = COPYRIGHT;
  71.  
  72. char    ttynam[NAMESIZE],        /* Name of tty we use as serial port */
  73.     srcnam[NAMESIZE],        /* Source file name */
  74.     dstnam[NAMESIZE],        /* Dest file name */
  75.     who[NAMESIZE] = "-",            /* Who sent the file */
  76.     flags[MAX_FLAGS],        /* Flags from file xfer cmd */
  77.     temp[NAMESIZE];         /* Temp file name */
  78.  
  79. int    ourpid = 0,            /* Our process ID */
  80.     ignore_time_restrictions = 0,    /* Call out even if L.sys sez no */
  81.     mode;                /* File mode from file xfer cmd */
  82.  
  83. char  host_name[MAX_HOST] = "AmigaUUCP";  /* Other guy's host name */
  84. char  our_name[MAX_HOST];    /* Our uucp hostname, set from usenet.ctl */
  85. char  path[128];
  86. int   debug   = -1;    /* -1 indicates not set by command line or ctl file */
  87. int   f_wait  = 0;    /* wait for a call (-w) or calls (-w -e) after outbnd */
  88. int   loop    = 0;    /* Loop accepting logins if tty name specified */
  89. int   Overide = 0;    /* overide modem protocol        */
  90. int   Getty   = 0;    /* -Getty initiated            */
  91. int   IgnoreCD= 0;    /* xgetc() should ignore carrier?   */
  92. int   OurNameOv= 0;
  93. int   WindowSize = 999;
  94. int   NoReScan = 0;    /* do not rescan for work after error    */
  95. int   SevenWire= 0;
  96. int   XDebug  = 0;    /* do not pass debug parameter to remote    */
  97. int   DebugHandshake = 0;
  98. int   PacketTimeout = 0;
  99. short ProtoHacks;     /*  protocol hacks  */
  100. short PriMode;
  101. short OldPri;
  102. short IgnoreDTR = 0;
  103.  
  104. #define MAX_STRING    200    /* Max length string to send/expect */
  105.  
  106. #define MSGO2IDX    6
  107.  
  108. /* We print these prompts */
  109.  
  110. char msgo0[] = "login: ";
  111. char msgo1[] = "Password:";
  112. char msgo2[10+MAX_HOST] = { "\20Shere" };   /*  NO =    */
  113. char msgo3[] = "\20ROK\0";
  114. char msgo3a[]= "\20P";
  115. char msgo3b[]= "\20Pg\0";
  116. char msgo4[] = "\20OOOOOOO\0";
  117.  
  118. /* We expect to receive these strings */
  119.  
  120. char msgi0[] = "uucp\r";
  121. char msgi1[] = "s8000\r";
  122. /* char msgi2[] = "\20S*\0"; We now scan it specially FIXME */
  123. char msgi3[] = "\20Ug\0";
  124. char msgi4[] = "OOOOOO";
  125.  
  126. /*
  127.  * Protocol switch data structure
  128.  */
  129.  
  130. #define turnon    gturnon
  131. #define rdmsg    grdmsg
  132. #define wrmsg    gwrmsg
  133. #define rddata    grddata
  134. #define wrdata    gwrdata
  135. #define turnoff gturnoff
  136.  
  137. int
  138. getname(isshere)
  139. int isshere;
  140. {
  141.     int data, count = 0;
  142.     static char msgi[MAX_STRING+SLOP];    /* Incoming trash buffer */
  143.  
  144.     /* Read data until null character */
  145.  
  146.     while ((data = xgetc(BYTE_TO)) != EOF) {
  147.     data &= 0x7F;
  148.     if (data == 020)
  149.         break;
  150.     }
  151.     if (data == EOF)
  152.     return FAIL;
  153.  
  154.     while ((data = xgetc(BYTE_TO)) != EOF && (data & 0x7F)) {
  155.     data &= 0x7F;
  156.     if (count == 0 && data != 'S')
  157.         continue;
  158.     if (count > sizeof(msgi) - 2)
  159.         continue;
  160.     if (data == 0x0A)       /*  hack fix for tuvie ? */
  161.         break;
  162.     msgi[count++] = (char)data;
  163.     }
  164.     msgi[count] = 0;
  165.  
  166.     if (debug > 8)
  167.     printf("GETNAME MSG (%d): %s\n", count, msgi);
  168.  
  169.     if (msgi[0] != 'S')
  170.     return FAIL;
  171.     if (isshere) {
  172.     for (count = 1; msgi[count] && msgi[count] != '='; ++count);
  173.     if (msgi[count] == '=')
  174.         ++count;
  175.     } else {
  176.     count = 1;
  177.     }
  178.     if (msgi[count]) {
  179.     if (debug > 8)
  180.         printf("Compare host names: '%s' '%s'\n", host_name, msgi + count);
  181.     strcpy (host_name, msgi + count);
  182.     }
  183.     strtok(host_name, " \t");     /*  put \0 after hostname */
  184.     if (debug > 8)
  185.     printf("Hostname is '%s'\n", host_name);
  186.     return SUCCESS;
  187. }
  188.  
  189. /*
  190.  *  get_proto() checks the list of protos given by the foriegn machine
  191.  *  checking for 'g' (which is the only proto we have).  Use only in master
  192.  *  mode.
  193.  */
  194.  
  195. int
  196. get_proto()
  197. {
  198.     int data;
  199.  
  200.     while ((data = xgetc(BYTE_TO)) != EOF) {
  201.     data &= 0x7F;
  202.     if (data == 0)
  203.         break;
  204.     if (data == 'g')
  205.         return(SUCCESS);
  206.     }
  207.     return FAIL;
  208. }
  209.  
  210. /*
  211.  * Medium level input routine.
  212.  *
  213.  * Look for an input string for the send-expect sequence.
  214.  * Return 0 for matching string, 1 for timeout before we found it.
  215.  * FIXME:  we only time out if the other end stops sending.  If it
  216.  *       keeps sending, we keep listening forever.
  217.  */
  218.  
  219. instr(s, n, to)
  220. char *s;
  221. int n;
  222. int to;     /*    timeout */
  223. {
  224.     int data,count,j;
  225.     int i;
  226.     static char msgi[512];  /* Incoming trash buffer */
  227.  
  228.     count = 0;
  229.     if (to == 0)
  230.     to = BYTE_TO;
  231.  
  232.     if (debug > 8) {
  233.     printf("Expecting ");
  234.     for (i = 0; i < n; i++)
  235.         printc(s[i]);
  236.     printf("\n");
  237.     }
  238.     if (DebugHandshake) {
  239.     printf("recvd: '");
  240.     fflush(stdout);
  241.     }
  242.  
  243.     while ((data = xgetc(to)) != EOF) {
  244.     data &= 0x7F;
  245.  
  246.     msgi[count++] = data;
  247.  
  248.     if (DebugHandshake) {
  249.         if (data < 0x20)
  250.         printf("^%c", data + '@');
  251.         else
  252.         printf("%c", data);
  253.         fflush(stdout);
  254.     }
  255.  
  256.     if (count == sizeof(msgi)) {    /*  throw away first half */
  257.         count = sizeof(msgi) / 2;
  258.         bcopy(msgi + sizeof(msgi) / 2, msgi, sizeof(msgi) / 2);
  259.     }
  260.  
  261.     if (count >= n) {
  262.         for (i = n - 1, j = count - 1; i >= 0; i--, j--) {
  263.         if (*(s+i) != msgi[j])
  264.             break;
  265.         }
  266.         if (i < 0) {
  267.         if (debug > 8)
  268.             printf("\n");
  269.         if (DebugHandshake)
  270.             printf("' (GOTIT!)\n");
  271.         return(0);
  272.         }
  273.     }
  274.     }
  275.     if (DebugHandshake)
  276.     printf("' (TIMEOUT!)\n");
  277.  
  278.     if (debug > 8)
  279.     printf("\n");
  280.     msgi[count] = (char)0;
  281.     return(1);
  282. }
  283.  
  284. /*
  285.  * Debugging hack for stuff written to the modem.
  286.  */
  287.  
  288. int
  289. twrite(s, n)
  290. const char *s;
  291. int  n;
  292. {
  293.     int i;
  294.  
  295.     if (debug > 8) {
  296.     printf("Wrote:  ");
  297.     for (i = 0; i < n; i++)
  298.         printc(s[i]);
  299.     printf("\n");
  300.     }
  301.     return xwrite(s, n);
  302. }
  303.  
  304. void
  305. myexit()
  306. {
  307.     long task = FindTask(NULL);
  308.     if (PriMode)
  309.     SetTaskPri(task, OldPri);
  310. }
  311.  
  312. /*
  313.  * MAIN ROUTINE.
  314.  *
  315.  * This is called at program startup.  It parses the arguments to the
  316.  * program (if any) and sets up to receive a call on the modem.
  317.  *
  318.  * If there are no arguments, we assume the caller is already on standard
  319.  * input, waiting to do uucp protocols (past the login prompt), and we
  320.  * just handle one caller.
  321.  *
  322.  * If there is an argument, it is the name of the tty device where we
  323.  * should listen for multiple callers and handle login and password.
  324.  */
  325.  
  326. main(argc,argv)
  327. int argc;
  328. char *argv[];
  329. {
  330.     int     i;
  331.     char    *poll_sys = (char *)NULL;   /* System name to poll, or none */
  332.     short   rmode = 0;            /* 1 = master, 0 = slave    */
  333.  
  334.     LogProgram = "uucico";
  335.     LogHost = host_name;
  336.     LogWho  = who;
  337.  
  338.     signal(SIGINT, sigint);
  339.     atexit(myexit);
  340.  
  341.     /* FIXME, use getopt */
  342.     /* scan command line arguments, kinda kludgy but it works */
  343.  
  344.     for (i = 1; i < argc; ++i) {
  345.     char *ptr = argv[i];
  346.  
  347.     if (*ptr != '-') {
  348.         printf("uucico: warning, extra args ignored: %s\n", argv[i]);
  349.         break;
  350.     }
  351.     ptr += 2;
  352.     switch (ptr[-1]) {
  353.     case 'N':
  354.         strcpy(our_name, ptr);
  355.         OurNameOv = 1;
  356.         break;
  357.     case 'D':       /*  Serial Device   */
  358.         {
  359.         extern char *DeviceName;
  360.         DeviceName = argv[++i];
  361.         }
  362.         break;
  363.     case 'U':       /*  Serial Unit     */
  364.         {
  365.         extern long DeviceUnit;
  366.         DeviceUnit = ((*ptr >= '0' && *ptr <= '9') ? atoi(ptr) : atoi(argv[++i]));
  367.         }
  368.         break;
  369.     case 'p':       /*  protocol hacks  */
  370.         if (strcmp(ptr, "ri") == 0) {   /*  -pri    */
  371.         long task = FindTask(NULL);
  372.  
  373.         PriMode = 1;
  374.         OldPri = SetTaskPri(task, 5);
  375.         SetTaskPri(task, OldPri + 1);
  376.         } else {                /*    -proto    */
  377.         ProtoHacks |= (*ptr) ? atoi(ptr) : atoi(argv[++i]);
  378.         }
  379.         break;
  380.     case 'g':
  381.     case 'G':
  382.         Getty = 1;
  383.         break;
  384.     case 'h':
  385.         IgnoreCD = 1;
  386.         break;
  387.     case 'w':
  388.         ++f_wait;
  389.         break;
  390.     case 'r':
  391.         rmode = atoi(&argv[i][2]);
  392.         break;
  393.     case 'X':
  394.         XDebug = 1;
  395.     case 'x':
  396.         if (argv[i][2] == 'x') {
  397.         DebugHandshake = 1;
  398.         break;
  399.         }
  400.  
  401.         debug = atoi(&argv[i][2]);
  402.         LogLevel = debug;
  403.         LogToStdout = 0;
  404.         printf("uucico: debug level set to %d\n", debug);
  405.         break;
  406.     case 'o':
  407.         Overide = 1;
  408.         break;
  409.     case 'n':
  410.         WindowSize = (*ptr) ? atoi(ptr) : 1;
  411.         break;
  412.     case 'b':
  413.         system(GetConfigProgram(BATCHNEWS));
  414.         break;
  415.     case 'S':
  416.         ignore_time_restrictions++;
  417.     case 's':
  418.         poll_sys = &argv[i][2];
  419.         break;
  420.     case 'e':
  421.         ++loop;
  422.         break;
  423.     case 't':
  424.         PacketTimeout = (*ptr) ? atoi(ptr) : atoi(argv[++i]);
  425.         break;
  426.     case '7':
  427.         SevenWire = 1;
  428.         break;
  429.     case 'd':
  430.         IgnoreDTR = (*ptr) ? !atoi(ptr) : 1;
  431.         break;
  432.     case 'H':
  433.         IgnoreCD = 1;
  434.         Overide = 1;
  435.         break;
  436.     case 'B':
  437.         i++;    /* throw away baud rate argument */
  438.         break;
  439.     default:
  440.         printf("uucico: warning, bad flag %s\n", argv[i]);
  441.         break;
  442.     }
  443.     }
  444.  
  445.     /* If argument provided, use it as name of comm port */
  446.  
  447.     /* FIXME, this needs some thought. */
  448.  
  449.     getcwd(path,128);
  450.     if (chdir(GetConfigDir(UUSPOOL))) {
  451.     perror("Can't chdir to Spool directory");
  452.     exit(2);
  453.     }
  454.  
  455.     read_ctl();
  456.  
  457.     /*
  458.      * If running via getty/login, our debug stdout had better
  459.      * go to a file, not to the usual stdout!
  460.      */
  461.  
  462.     if (debug > 0 && Getty) {
  463.     freopen("T:uuslave.log", "a", stdout);
  464.     }
  465.  
  466.     /*setvbuf(stdout, NULL, _IOLBF, 0);*/
  467.  
  468.     /* Timestamp the long debug log */
  469.  
  470.     if (debug > 0) {
  471.     long clock;
  472.  
  473.     time(&clock);
  474.     printf("\014\nuuslave log on tty '%s' starting %s\n",
  475.         ttynam, ctime(&clock));
  476.     }
  477.  
  478.     /* Log our presence so we humans reading the logs can find the
  479.        entries created by uuslave. */
  480.  
  481.     ulog(-1, "Startup %s", VERSION);
  482.  
  483.     amiga_setup();
  484.  
  485.     modem_init();
  486.  
  487.     if (poll_sys) {
  488.     if (*poll_sys == '\0')
  489.         poll_sys = (char *)NULL;
  490.     call_system(poll_sys, rmode);
  491.     if (!f_wait)
  492.         goto end;
  493.     } else {
  494.     if (rmode) {
  495.         do_outbound();
  496.         if (!f_wait)
  497.         goto end;
  498.     }
  499.     }
  500.  
  501.     do {
  502.     /*
  503.      *  Set up serial channel, wait for incoming call.
  504.      */
  505.     DEBUG(0, "\nRestarting\n", 0);
  506.  
  507.     if (Getty == 0 && Overide == 0)
  508.         openline();
  509.  
  510.     do_session(Getty);
  511.  
  512.     hangup();
  513.     DEBUG(0, "\nEnd of call\n", 0);
  514.     } while (loop && !Getty);
  515.  
  516. end:
  517.     cleanup();
  518.     return(0);
  519. }
  520.  
  521. /*
  522.  * translate embedded escape characters
  523.  */
  524.  
  525. void
  526. xlat_str(msg)
  527. char    *msg;
  528. {
  529.     int i  = 0;
  530.     int cr = 1;
  531.  
  532.     while (msg[i]) {
  533.     if (msg[i] == '\\') {
  534.         switch (msg[++i]) {
  535.         case 'r':            /* carriage return */
  536.         twrite("\r", 1);
  537.         break;
  538.         case 'n':            /* line feed */
  539.         twrite("\n", 1);
  540.         break;
  541.         case '\\':           /* back slash */
  542.         twrite("\\", 1);
  543.         break;
  544.         case 't':            /* tab */
  545.         twrite("\t", 1);
  546.         break;
  547.         case 'b':
  548.         SendBreak();
  549.         break;
  550.         case 'd':            /* delay */
  551.         Delay(180);
  552.         break;
  553.         case 's':            /* space */
  554.         twrite(" ", 1);
  555.         break;
  556.         case 'c':            /* no CR at end */
  557.         cr = 0;
  558.         break;
  559.         default:        /* don't know so skip it */
  560.         break;
  561.         }
  562.         ++i;
  563.     } else {
  564.         twrite(msg + i, 1);
  565.         ++i;
  566.     }
  567.     }
  568.     if (cr) {
  569.     twrite("\r", 1);
  570.     }
  571. }
  572.  
  573. /*
  574.  * Read the control file and grab a few parameters.
  575.  */
  576.  
  577. int
  578. read_ctl()
  579. {
  580.     char *nodename = FindConfig(NODENAME);
  581.     char *debugstr = FindConfig(DEBUGNAME);
  582.  
  583.     if (nodename && OurNameOv == 0)
  584.     strcpy(our_name, nodename);
  585.     if (debugstr && debug < 0)
  586.     debug = atoi(debugstr);
  587.     return (1);
  588. }
  589.  
  590. /*
  591.  * Search spool queues for work, call the systems we need to call.
  592.  */
  593.  
  594. int
  595. do_outbound()
  596. {
  597.     return call_system((char *)NULL, 1);
  598. }
  599.  
  600. /*
  601.  * Call a specific system, or all systems that have work pending.
  602.  */
  603.  
  604. int
  605. call_system(sys, ifworkpend)
  606. char    *sys;
  607. {
  608.     FILE    *lsys;
  609.     static char buf[MAX_LSYS];
  610.     static char sysnam[MAX_HOST];
  611.     static char prev_name[MAX_HOST];
  612.     int     called = FAIL;
  613.  
  614.     /*
  615.      * Unix uucico just reads the directory, and calls the systems
  616.      * in the order of the files in the directory.  We want more
  617.      * control than that, though I'm not sure that L.sys order is
  618.      * best either.  For example, in the first call after 11PM,
  619.      * I'd like to call the sites that haven't been callable before
  620.      * 11PM first, and finish up with the ones I've been able to call
  621.      * all day.  FIXME.
  622.      */
  623.  
  624.     if (! (lsys = fopen(MakeConfigPath(UULIB, "L.sys"), "r"))) {
  625.     DEBUG(0, "uucico: can't open L.sys, errno %d\n", errno);
  626.     return 0;
  627.     }
  628.     sysnam[0] = '\0';               /* Initially, no previous sys */
  629.  
  630.     /* Once per system in L.sys... */
  631.     /* FIXME, handle continuation lines (trailing "\") */
  632.  
  633.     while (fgets(buf, sizeof buf, lsys)) {
  634.     if (buf[0] == '#' || buf[0] == '\n')
  635.         continue;
  636.  
  637.     /*
  638.      * Grab the system name.  If same as previous, and
  639.      * the previous call worked, skip it.
  640.      */
  641.  
  642.     strcpy(prev_name, sysnam);
  643.     (void) sscanf(buf, "%s", sysnam);
  644.     if (!strcmp(sysnam, prev_name)) {
  645.         if (called == SUCCESS)
  646.         continue;
  647.     }
  648.  
  649.     /*
  650.      * If a system name was specified, skip til we find it
  651.      * If none was specified, only call if there is work.
  652.      */
  653.  
  654.     if (sys) {
  655.         if (strcmp(sys, sysnam) != 0)
  656.         continue;
  657.         if (ifworkpend && !work_scan(sysnam)) {
  658.         ulog(-1, "No work for system %s", sysnam);
  659.         called = SUCCESS;
  660.         continue;
  661.         }
  662.     } else {
  663.         DEBUG(3,"searching for outbound to %s\n", sysnam);
  664.         if (!work_scan(sysnam)) {
  665.         DEBUG(3,"no work for %s\n", sysnam);
  666.         called = SUCCESS;    /* Don't try further */
  667.         continue;
  668.         }
  669.         DEBUG(2, "uucico: found work for %s\n", sysnam);
  670.     }
  671.  
  672.     called = call_sysline(buf);
  673.  
  674.     if (called == SUCCESS && sys)
  675.         break;
  676.     }
  677.  
  678.     fclose(lsys);
  679.     if (called == FAIL && sys)
  680.     DEBUG(0, "Could not call system %s\n", sys);
  681.     return 0;
  682. }
  683.  
  684. /*
  685.  *  Call out to a system, given its L.sys line.
  686.  */
  687.  
  688. int
  689. call_sysline(lsysline)
  690. char *lsysline;
  691. {
  692.     static char    tempname[MAX_HOST + 30 + SLOP];
  693.     char    *sysnam,
  694.         *times,
  695.         *acu,
  696.         *sbaud,
  697.         *telno,
  698.         *send,
  699.         *expct;
  700.     int     baud;
  701.  
  702.     who[0] = '-'; who[1] = '\0';    /* No user now (for logit) */
  703.  
  704.     /* FIXME, use the values it is ignoring here */
  705.  
  706.     sysnam = strtok(lsysline, " \t");
  707.     times =  strtok(NULL, " \t");   /* Time */
  708.     acu =    strtok(NULL, " \t");   /* ACU  */
  709.     sbaud =  strtok(NULL, " \t");   /* Baud */
  710.     telno =  strtok(NULL," \t");    /* phone*/
  711.  
  712.     strcpy(host_name, sysnam);
  713.  
  714.     if (ignore_time_restrictions == 0) {
  715.     if (CheckTimeRestrictions(times) == FAIL) {
  716.         ulog(-1, "Wrong Time To Call %s", sysnam);
  717.         return(FAIL);
  718.     }
  719.     }
  720.  
  721.     baud = atoi(sbaud);
  722.  
  723.     /*    FIX ME, acu not implemented ?    */
  724.     DEBUG(4, "Opening outgoing line %s\n", acu);
  725.     if (openout(acu, baud) != SUCCESS)
  726.     return FAIL;
  727.  
  728.     if (Overide == 0) {
  729.     if (dial_nbr(telno)) {
  730.         ulog(-1, "FAILED call to %s", host_name);
  731.         return FAIL;
  732.     }
  733.     }
  734.  
  735.     /* FIXME, log tty, baud rate, ... */
  736.     ulog(-1, "DIALED %s", host_name);
  737.  
  738.     /*
  739.      * Process send-expect strings.
  740.      * FIXME, deal with "-", BREAK, etc.
  741.      */
  742.  
  743.     if (DebugHandshake)
  744.     puts("CONNECTED, running send-expect strings");
  745.  
  746.     while (send = (char*)strtok((char *)NULL, " \t\n")) {
  747.     if (send[0] != '"' || send[1] != '"' || send[2] != '\0') {
  748.         if (DebugHandshake)
  749.         printf("Expect %s\n", send);
  750.         if (instr(send, strlen(send), 0))
  751.             goto bort1;
  752.     } else if (DebugHandshake) {
  753.         puts("Expect Nothing");
  754.     }
  755.  
  756.     if (expct = (char*)strtok((char *)NULL, " \t\n")) {
  757.         if (DebugHandshake)
  758.         printf("Send: %s\n", expct);
  759.         /* FIXME secondary strings, e.g. ogin:-EOT-ogin: */
  760.         xlat_str(expct);
  761.     }
  762.     }
  763.  
  764.     /*
  765.      * FIXME, there should be a way to detect login/passwd
  766.      * failure here and keep doing the script rather than
  767.      * continuing to expect Shere at another login: prompt.
  768.      */
  769.  
  770.     ulog(-1, "SUCCEEDED call to %s", host_name);
  771.  
  772.  
  773.     if (getname(1))         /*  get name        */
  774.     goto bort1;
  775.                 /*    send response    */
  776.     sprintf(tempname, "\20S%s -Q0 -x%d\0", our_name, (XDebug) ? 0 : debug);
  777.     twrite(tempname, strlen(tempname)+1); /* Including null */
  778.  
  779.     /* wait for ok message, wait for protocol request
  780.      * send protocol 'g' response */
  781.     /* FIXME, we don't actually wait for the ROK message, since
  782.      * it is immediately followed by the Pprotos message.  We
  783.      * currently just look for a Pg message.  This needs work.
  784.      * FIXME, WE CAN'T TALK TO SITES THAT SUPPORT more than 'g'.
  785.      */
  786.  
  787.     if (instr(msgo3a, sizeof(msgo3a)-1, 0)) {
  788.     if (!get_proto())
  789.        goto bort1;
  790.     }
  791.  
  792.  
  793.     twrite( msgi3, sizeof(msgi3)-1);
  794.  
  795.     ResetGIO();                         /* reset GIO protocol   */
  796.  
  797.     if (turnon(1))
  798.     goto bort1;
  799.  
  800.     ulog(-1, "OK Startup");
  801.  
  802.     top_level(1);
  803.     hangup();
  804.     return SUCCESS;
  805.  
  806. bort1:
  807.     hangup();
  808.     return FAIL;
  809. }
  810.  
  811. /* Handle a single uucp [slave] login session */
  812.  
  813. int
  814. do_session(ontheline)
  815. int ontheline;
  816. {
  817.     if (ontheline == 0) {
  818.     /* output login request, verify uucp */
  819.     twrite(msgo0,sizeof(msgo0)-1);
  820.     if (instr(msgi0, sizeof(msgi0)-1, 0)) {
  821.         printf("uucico: invalid login name\n");
  822.         goto bort;
  823.     }
  824.  
  825.     /* output password request, verify s8000 */
  826.     twrite(msgo1,sizeof(msgo1)-1);
  827.     if (instr(msgi1, sizeof(msgi1)-1, 0)) {
  828.         printf("uucico: invalid password\n");
  829.         goto bort;
  830.     }
  831.  
  832.     printf("uucico: correct login\n");
  833.     }
  834.  
  835.     /*
  836.      *    send Shere=<myhost>
  837.      *
  838.      *    Apparently mac UUCP has a bug that only allows 7
  839.      *    char host names, and it fails if it gets shere=<myhost>
  840.      *    where <myhost> is > 7 chars.
  841.      *
  842.      *    Apparently some implementations of AmigaUUCP do not accept
  843.      *    an SHere with an =<myhost>, so this is disabled unless -p1 is used.
  844.      */
  845.  
  846.     if (ProtoHacks & PROTOF_SHEREEQUALS)
  847.     sprintf(msgo2 + MSGO2IDX, "=%s", our_name);
  848.     twrite(msgo2,strlen(msgo2)+1);
  849.  
  850.     /*
  851.      *    get \020S<host> -Qn n    (??)
  852.      */
  853.  
  854.     if (getname(0))
  855.     goto bort;
  856.  
  857.     /* output ok message, output protocol request, wait for response */
  858.  
  859.     twrite(msgo3,sizeof(msgo3)-1);
  860.  
  861.     /* FIXME, make the protocol list here, and use it */
  862.     twrite(msgo3b,sizeof(msgo3b)-1);
  863.     if (instr(msgi3, sizeof(msgi3)-1, 0))
  864.         goto bort;
  865.  
  866.     ResetGIO();                         /* reset GIO protocol   */
  867.  
  868.     if (turnon(0))
  869.     goto bort;
  870.  
  871.     ulog(-1, "OK Startup");
  872.     top_level(0);
  873.  
  874. bort:
  875.     if (debug > 0)
  876.     printf("uucico: call complete\n");
  877.     return (1);
  878. }
  879.  
  880. /*
  881.  * Handle transactions "at top level", as Unix uucp's debug log says.
  882.  *
  883.  * As master, we scan our queues for work and send requests to the
  884.  * other side.    When done, we send a hangup request and switch to slave mode.
  885.  *
  886.  * As slave, we accept requests from the other side; when it is done,
  887.  * it sends a hangup request, and we switch to master mode, if we have
  888.  * any work queued up for that system.
  889.  *
  890.  * This repeats as long as either side has work to do.    When all the
  891.  * queued work is done, we agree to hang up, terminate the packet protocol,
  892.  * and return to the caller.  (We still haven't hung up the phone line yet.)
  893.  *
  894.  * A curious feature of the hangup protocol is that it is not a simple
  895.  * question-answer.  The master says "H", asking about hangup.  The
  896.  * slave responds "HY" saying OK.  The master then says "HY" also,
  897.  * then both of them hang up.  Maybe this is to make sure the first HY
  898.  * got ack'ed?  Anyway, an "H" is reported as HANGUP and an "HY" as
  899.  * HANGNOW.  After we send an HY, we go back to listening for commands;
  900.  * if the master sends something other than HY, we'll do it.
  901.  */
  902.  
  903. #define HANGUP    2        /* Signal to switch master/slave roles */
  904. #define HANGNOW 3        /* Signal to hang up now */
  905. #define COPYFAIL    4    /* File copy failed */
  906.  
  907. int
  908. top_level(master_mode)
  909. int master_mode;
  910. {
  911.     static char    buf[MAXMSGLEN];    /* For hangup responses */
  912.  
  913.  
  914.     if (master_mode) {
  915.     (void) work_scan(host_name);    /* Kick off queue scan */
  916.     goto master;
  917.     }
  918.  
  919.     for (;;) {
  920.     slave:            /*  SLAVE SIDE    */
  921.     for (;;) {
  922.         DEBUG(4, "*** TOP *** - slave\n", 0);
  923.         switch (do_one_slave()) {
  924.         case SUCCESS:
  925.         break;
  926.         case FAIL:
  927.         DEBUG(4, "*** DO_ONE_SLAVE FAIL *** - slave\n", 0);
  928.         return FAIL;
  929.         case HANGUP:
  930.         if (work_scan(host_name)) {
  931.             if (wrmsg("HN") != SUCCESS) {
  932.             DEBUG(4, "*** WRMSG HN FAIL *** - slave\n", 0);
  933.             return FAIL;
  934.             }
  935.             goto master;
  936.         } else {
  937.             if (wrmsg("HY") != SUCCESS) {
  938.             DEBUG(4, "*** WRMSG HY FAIL *** - slave\n", 0);
  939.             return FAIL;
  940.             }
  941.             break;    /*  go to master mode */
  942.         }
  943.         case HANGNOW:
  944.         goto quit;
  945.         }
  946.     }
  947.     master:    /*  MASTER SIDE */
  948.     for (;;) {
  949.         DEBUG(4, "*** TOP *** - master\n", 0);
  950.         switch (do_one_master()) {
  951.         case SUCCESS:
  952.         break;
  953.         case FAIL:
  954.         DEBUG(4, "*** DO_ONE_MASTER FAIL *** - master\n", 0);
  955.         return FAIL;
  956.         case HANGUP:
  957.         /* We wrote an H command, what's the resp? */
  958.         if (rdmsg(buf, MAXMSGLEN) != SUCCESS) {
  959.             DEBUG(4, "*** RDMSG HANGUP FAIL *** - master\n", 0);
  960.             return FAIL;
  961.         }
  962.         if (buf[0] != 'H') {
  963.             DEBUG(4, "*** RDMSG HANGUP != 'H' *** - master\n", 0);
  964.             return FAIL;
  965.         }
  966.         if (buf[1] == 'N') {
  967.             goto slave;
  968.         } else {
  969.             /*
  970.              *    send final HY?    not sure if this should happen, will
  971.              *    necessarily fail if the other side does not expect
  972.              *    it so do not return... continue on w/ exit code.
  973.              *
  974.              *    however, reduce timeout parameters
  975.              */
  976.  
  977.             ++ReducedTimeout;
  978.             wrmsg("HY");
  979.             --ReducedTimeout;
  980.             goto quit;
  981.         }
  982.         }
  983.     }
  984.     }
  985.  
  986. quit:
  987.     /* Shut down the packet protocol */
  988.  
  989.     turnoff();
  990.  
  991.     /* Write the closing sequence */
  992.  
  993.     twrite(msgo4, sizeof(msgo4)-1);
  994.     (void) instr(msgi4, sizeof(msgi4)-1, 0);
  995.  
  996.     twrite(msgo4, sizeof(msgo4)-1);
  997.  
  998.     strcpy(who, "-");
  999.     ulog(-1, "OK Conversation complete");
  1000.  
  1001.     return SUCCESS;   /* Go byebye */
  1002. }
  1003.  
  1004. /*
  1005.  * We are slave; get a command from the other side and execute it.
  1006.  *
  1007.  * Result is SUCCESS, FAIL, HANGUP, or HANGNOW.
  1008.  */
  1009.  
  1010. int
  1011. do_one_slave()
  1012. {
  1013.     static char msg[MAXMSGLEN];        /* Master's message to us */
  1014.  
  1015.     /* Get master's command */
  1016.     if (rdmsg(msg, MAXMSGLEN) != SUCCESS)
  1017.     return FAIL;
  1018.  
  1019.     /* Print it for easy debugging */
  1020.     DEBUG(5,"\nCommand: %s\n\n", msg);
  1021.  
  1022.     switch (msg[0]) {
  1023.     case 'S':
  1024.     if (msg[1] != ' ')
  1025.         break;
  1026.     return host_send_file(msg);
  1027.     case 'R':
  1028.     if (msg[1] != ' ')
  1029.         break;
  1030.     return host_receive_file(msg);
  1031.     case 'X':
  1032.     break;
  1033.     case 'H':
  1034.     if (msg[1] == '\0') return HANGUP;
  1035.     if (msg[1] == 'Y')  return HANGNOW;
  1036.     if (msg[1] == 'N')  return SUCCESS;     /* Ignore HN to slave */
  1037.     break;
  1038.     }
  1039.  
  1040.     /* Unrecognized packet from the other end */
  1041.  
  1042.     DEBUG(0, "Bad control packet refused: %s\n", msg);
  1043.     return(yesno(msg[0], 0, 0));
  1044. }
  1045.  
  1046. /*
  1047.  *  Do one piece of work as master.
  1048.  *
  1049.  *  FIXME:  we don't handle the flags, e.g. -c, properly!
  1050.  *
  1051.  *  Now only dequeues queue file if all transfers were successful.
  1052.  */
  1053.  
  1054. int
  1055. do_one_master()
  1056. {
  1057.     FILE    *fd;
  1058.     char    *sname;
  1059.     static char cmnd[256];        /* Command character */
  1060.     static char buf[256];
  1061.     int     fail = SUCCESS;
  1062.     int     failAction = SUCCESS;
  1063.     int     failaccum = 0;
  1064.     int     num;
  1065.     int     delmeflag;
  1066.     static char notify[NAMESIZE];   /* A bit large...FIXME */
  1067.     char    *delList[16];        /* delete files list   */
  1068.     short   di = 0;
  1069.  
  1070.     /*
  1071.      *    Get the next work item.  If no work left re-scan the directory
  1072.      *    just to be sure, and if still no work then do the right thing.
  1073.      */
  1074.  
  1075.     sname = work_next();
  1076.     if (!sname && NoReScan == 0) {
  1077.     if (work_scan(host_name))
  1078.         sname = work_next();
  1079.     }
  1080.     if (!sname) {
  1081.     /* No more work, time to hang up. */
  1082.     if (wrmsg("H") != SUCCESS)
  1083.         return FAIL;
  1084.     return HANGUP;
  1085.     }
  1086.  
  1087.     DEBUG(2, "Request file %s\n", sname);
  1088.  
  1089.     LockFile(sname);
  1090.  
  1091.     fd = fopen(sname, "r");
  1092.     if (fd == NULL) {
  1093.     UnLockFile(sname);
  1094.     DEBUG(0, "uucico: couldn't open %s\n", sname);
  1095.     return SUCCESS;
  1096.     }
  1097.  
  1098.     while (fgets(buf, sizeof(buf), fd)) {
  1099.     DEBUG(3, "Queued request: %s", buf);
  1100.  
  1101.     if (buf[1] != ' ')
  1102.         goto badnum;
  1103.  
  1104.     num = sscanf(buf, "%s %s %s %s %s %s %o\n",
  1105.         cmnd, srcnam, dstnam, who, flags, temp, &mode, notify
  1106.     );
  1107.  
  1108.     switch (cmnd[0]) {
  1109.     case 'S':
  1110.         if (num < 7 || num > 8)
  1111.         goto badnum;
  1112.         fail = local_send_file(buf, &delmeflag);
  1113.         if (delmeflag) {
  1114.         if (di == sizeof(delList)/sizeof(delList[0])) {
  1115.             ulog(-1, "Too many source files in Cmd file! %s", sname);
  1116.         } else {
  1117.             delList[di] = malloc(strlen(temp) + 1);
  1118.             strcpy(delList[di], temp);
  1119.             ++di;
  1120.         }
  1121.         }
  1122.         break;
  1123.     case 'R':
  1124.         if (num != 5) {
  1125.         if (debug > 7)
  1126.             printf("Invalid scanf %d/5 :%s:%s:%s\n", num, cmnd, srcnam, dstnam);
  1127.         goto badnum;
  1128.         }
  1129.         fail = local_receive_file();
  1130.         break;
  1131.     default:
  1132.     badnum:
  1133.         ulog(-1, "Illegal Work Request (%s): %s", sname, buf);
  1134.         fail = REFUSED;
  1135.         break;
  1136.     }
  1137.  
  1138.     switch(fail) {
  1139.     case SUCCESS:
  1140.         break;
  1141.     case FAIL:
  1142.         ++failaccum;
  1143.         if (failAction == SUCCESS)
  1144.         failAction = FAIL;
  1145.         ulog(-1, "Protocol Failure at (%s): %s", sname, buf);
  1146.         NoReScan = 1;
  1147.         break;
  1148.     case REFUSED:
  1149.         ++failaccum;
  1150.         failAction = REFUSED;
  1151.         ulog(-1, "Work Refused (%s): %s", sname, buf);
  1152.         break;
  1153.     }
  1154.     }
  1155.     fclose(fd);
  1156.  
  1157.     switch(failAction) {
  1158.     case SUCCESS:
  1159.     while (di) {
  1160.         --di;
  1161.         remove(delList[di]);
  1162.         free(delList[di]);
  1163.     }
  1164.     fail = remove(sname);
  1165.     UnLockFile(sname);
  1166.     if (fail != 0) {
  1167.         ulog(-1, "Unable to remove work file %s", sname);
  1168.         DEBUG(0, "Can't remove, errno %d\n", errno);
  1169.     } else {
  1170.         DEBUG(4, "Removed work file %s\n", sname);
  1171.     }
  1172.     break;
  1173.     case FAIL:
  1174.     UnLockFile(sname);
  1175.     break;
  1176.     case REFUSED:
  1177.     UnLockFile(sname);
  1178.     strcpy(buf, sname);
  1179.     {
  1180.         short i;
  1181.         for (i = strlen(buf); i >= 0 && buf[i] != ':' && buf[i] != '/'; --i);
  1182.         ++i;
  1183.         if ((buf[i]|0x20) == 'c')
  1184.         buf[i] = 'E';
  1185.     }
  1186.     if (strcmp(sname, buf) == 0) {
  1187.         ulog(-1, "Removing %s", sname);
  1188.         remove(sname);
  1189.     } else {
  1190.         ulog(-1, "Renaming %s to %s", sname, buf);
  1191.         rename(sname, buf);
  1192.     }
  1193.     break;
  1194.     }
  1195.     return(SUCCESS);
  1196. }
  1197.  
  1198. /*
  1199.  *  Send a yes/no packet
  1200.  */
  1201.  
  1202. int
  1203. yesno(c, true, err)
  1204. char c;
  1205. int true;
  1206. int err;
  1207. {
  1208.     char buf[21];
  1209.  
  1210.     buf[0] = c;
  1211.     buf[1] = true? 'Y': 'N';
  1212.     buf[2] = 0;
  1213.     if (err && !true)
  1214.     sprintf(buf+2,"%d", err);
  1215.  
  1216.     return (wrmsg(buf));
  1217. }
  1218.  
  1219. /*
  1220.  *  SLAVE MODE, Master wishes to send a file to us
  1221.  *
  1222.  *  SECURITY:    If file is not in list of allowed directories
  1223.  *        disallow transfer.  UUSPOOL:   is always in the
  1224.  *        list.
  1225.  *
  1226.  *        If file is for UUSPOOL: (the current dir), disallow "C." files
  1227.  *        NOTE: success return and file redirected to T: as this can
  1228.  *        occur only if somebody purposefully is trying to break us.
  1229.  *
  1230.  *  Return 0 = success
  1231.  */
  1232.  
  1233. int
  1234. host_send_file(msg)
  1235. char  *msg;
  1236. {
  1237.     FILE *fddsk;            /* Disk file pointer */
  1238.     static char cmnd[256];        /* Command character */
  1239.     int r;
  1240.     int nor = 0;
  1241.  
  1242.     sscanf(msg,"%s %s %s %s %s %s %o",
  1243.         cmnd, srcnam, dstnam, who, flags, temp, &mode);
  1244.  
  1245.     ulog(-1, "REQUESTED %s", msg);
  1246.     munge_filename(dstnam, dstnam);           /* Translate to local name */
  1247.     strcpy (temp, TmpFileName(dstnam));       /* Create a handy temp file */
  1248.  
  1249.     if (SecurityDisallow(dstnam, 'w')) {
  1250.     ulog(-1, "REQUEST FAILED -- SECURITY");
  1251.     return(yesno('S', 0, 4));
  1252.     }
  1253.     if (SecurityDisallow(dstnam, 'c') > 0) {
  1254.     ulog(-1, "REQUEST FAILED -- SECURITY, REMOTE TRIED TO SEND");
  1255.     ulog(-1, "US A COMMAND FILE: %s, FILE COPIED TO T:Bad-Cmd", dstnam);
  1256.     strcpy(dstnam, "T:Bad-Cmd");
  1257.     nor = 1;
  1258.     }
  1259.  
  1260.     /* FIXME: deal with file modes now that we fopen. */
  1261.  
  1262.     LockFile(temp);
  1263.  
  1264.     fddsk = fopen(temp, "wb" /*, mode|0600 */);
  1265.     if (fddsk == NULL) {
  1266.     UnLockFile(temp);
  1267.     /* Can't open file -- send error response */
  1268.     if (debug > 0) {
  1269.         printf("Cannot open temp file %s (%s) for writing, errno=%d\n",
  1270.         temp,
  1271.         dstnam,
  1272.         errno
  1273.         );
  1274.     }
  1275.     ulog(-1, "REQUEST FAILED -- TEMP FILE");
  1276.     return (yesno('S', 0, 4));
  1277.     }
  1278.  
  1279.     /* FIXME: Are the above permissions right?? */
  1280.     /* FIXME: Should we create directories for the file? */
  1281.  
  1282.     if (yesno('S',1, 0) != SUCCESS) {
  1283.     fclose(fddsk);
  1284.     unlink(temp);
  1285.     UnLockFile(temp);
  1286.     return(FAIL);
  1287.     }
  1288.     r = receive_file(fddsk, temp, dstnam, srcnam, nor);
  1289.     UnLockFile(temp);
  1290.     return(r);
  1291. }
  1292.  
  1293. /*
  1294.  *  SLAVE MODE, Master wants us to send a file to it
  1295.  *
  1296.  *  SECURITY:    If file is not in list of allowed directories
  1297.  *        disallow transfer.  UUSPOOL:   is always in the
  1298.  *        list.
  1299.  *
  1300.  *  0 = sucess
  1301.  */
  1302.  
  1303. int
  1304. host_receive_file(msg)
  1305. char  *msg;
  1306. {
  1307.     FILE *fddsk;     /* Disk file descriptor */
  1308.     int x;
  1309.     static char cmnd[256];          /* Command character */
  1310.  
  1311.     ulog(-1, "REQUESTED %s", msg);
  1312.  
  1313.     sscanf(msg,"%s %s %s",cmnd,srcnam,dstnam);
  1314.     munge_filename(srcnam, temp);
  1315.  
  1316.     if (SecurityDisallow(temp, 'r')) {
  1317.     ulog(-1, "COPY FAILED -- SECURITY");
  1318.     return (yesno('S', 0, 4));
  1319.     }
  1320.  
  1321.     fddsk = fopen(temp, "rb");              /* Try to open the file */
  1322.     if (fddsk == NULL) {
  1323.     /* File didn't open, sigh. */
  1324.     if (debug > 0) {
  1325.         printf("Cannot open file %s (%s) for reading, errno=%d\n",
  1326.         temp, srcnam, errno
  1327.         );
  1328.     }
  1329.     ulog(-1, "DENIED CAN'T OPEN %s", temp);
  1330.     return(yesno('R', 0, 2));
  1331.     }
  1332.  
  1333.     if (yesno('R',1, 0) != SUCCESS) {
  1334.     fclose(fddsk);
  1335.     return(FAIL);
  1336.     }
  1337.  
  1338.     x = send_file(fddsk);
  1339.  
  1340.     switch (x) {
  1341.     default:
  1342.     return x;
  1343.     case COPYFAIL:
  1344.     /* We don't care if the copy failed, since the master
  1345.        asked for the file and knows the result. */
  1346.     return SUCCESS;
  1347.     }
  1348.     return 1;
  1349. }
  1350.  
  1351. /*
  1352.  *  MASTER MODE, We want to send a file.
  1353.  *
  1354.  *  Return FAIL, SUCCESS, or COPYFAIL.
  1355.  *
  1356.  *  SUCCESS is returned either if the file was not found locally (local
  1357.  *  error, and the queued transfer should be flushed) or if it was moved
  1358.  *  successfully.  COPYFAIL indicates that the queued transfer should be
  1359.  *  left queued, and later retried.  FIXME, there are several failure points
  1360.  *  in the transaction and we need finer control here.
  1361.  */
  1362.  
  1363. int
  1364. local_send_file(workstr, delmeflag)
  1365. char *workstr;
  1366. int *delmeflag;
  1367. {
  1368.     static char buf[MAXMSGLEN];    /* Used for both xmit and receive */
  1369.     FILE *fddsk;        /* Disk file descriptor */
  1370.     int res;            /* Result and file removal status */
  1371.  
  1372.     *delmeflag = 0;
  1373.  
  1374.     /* WHY are temp and srcnam switched?  FIXME!  And no notify? */
  1375.  
  1376.     sprintf(buf,"S %s %s %s %s %s 0%o %s",
  1377.     temp, dstnam, who, flags, srcnam, mode, who
  1378.     );
  1379.  
  1380.     ulog(-1, "REQUEST %s", buf);
  1381.  
  1382.     if (strchr(flags, 'c')) {
  1383.     munge_filename(srcnam, temp);
  1384.     } else {
  1385.     munge_filename(temp, temp);
  1386.     }
  1387.     LockFile(temp);
  1388.     fddsk = fopen(temp, "rb");
  1389.     if (fddsk == NULL) {
  1390.     UnLockFile(temp);
  1391.     /* FIXME -- handle queued request for nonexistent file */
  1392.     if (debug > 0)
  1393.         printf("Can't open file %s (%s), errno=%d\n",
  1394.         temp,
  1395.         srcnam,
  1396.         errno
  1397.         );
  1398.     ulog(-1, "NOT FOUND %s", temp);
  1399.     /* return COPYFAIL;*/
  1400.     return SUCCESS;     /*    assume file previously sent */
  1401.     }
  1402.  
  1403.     /* Tell the other side we want to send this file */
  1404.  
  1405.     if (wrmsg(buf) != SUCCESS) {
  1406.     fclose(fddsk);
  1407.     UnLockFile(temp);
  1408.     return (FAIL);
  1409.     }
  1410.  
  1411.     /* See what they have to say about it */
  1412.  
  1413.     if (rdmsg(buf, MAXMSGLEN) != SUCCESS) {
  1414.     fclose(fddsk);
  1415.     UnLockFile(temp);
  1416.     return FAIL;
  1417.     }
  1418.     if ((buf[0] != 'S') || (buf[1] != 'Y')) {
  1419.     ulog(-1, "REQUEST DENIED %s", buf);
  1420.     fclose(fddsk);
  1421.     UnLockFile(temp);
  1422.     return(REFUSED);
  1423.     }
  1424.     res = send_file(fddsk); /* FAIL, SUCCESS, or COPYFAIL */
  1425.  
  1426.     /* Delete the source file if it was just a copy */
  1427.  
  1428.     if (res != SUCCESS) {
  1429.     UnLockFile(temp);
  1430.     return res;
  1431.     }
  1432.     if (strchr(flags, 'c')) {   /* If copied direct from source */
  1433.     UnLockFile(temp);
  1434.     return res;        /* ...just return. */
  1435.     }
  1436.     *delmeflag = 1;
  1437.     UnLockFile(temp);
  1438.  
  1439.     return res;
  1440. }
  1441.  
  1442. /*
  1443.  *  MASTER MODE, We wish to receive a specific file so we ask for it
  1444.  *
  1445.  *  Return 0 = success
  1446.  */
  1447.  
  1448. int
  1449. local_receive_file()
  1450. {
  1451.     static char buf[MAXMSGLEN];
  1452.     FILE *fddsk;            /* Disk file pointer */
  1453.     int r;
  1454.  
  1455.     /* FIXME, test dest file access before we ask for it. */
  1456.  
  1457.     sprintf(buf,"R %s %s %s %s %s 0%o %s",
  1458.     srcnam, dstnam, who, flags, temp, mode, who
  1459.     );
  1460.  
  1461.     munge_filename(dstnam, dstnam);           /* tlate to local name      */
  1462.     strcpy (temp, TmpFileName(dstnam));       /* Create a handy temp file */
  1463.  
  1464.     /* FIXME: deal with file modes now that we fopen. */
  1465.     /* FIXME: Are the above permissions right?? */
  1466.     /* FIXME: Should we create directories for the file? */
  1467.  
  1468.     LockFile(temp);
  1469.     fddsk = fopen(temp, "wb" /*, mode|060 */);
  1470.  
  1471.     if (fddsk == NULL) {
  1472.     UnLockFile(temp);
  1473.     /* Can't open temp file -- send error response */
  1474.     if (debug > 0) {
  1475.         printf("Cannot open temp file %s (%s) for writing, errno=%d\n",
  1476.         temp,
  1477.         dstnam,
  1478.         errno
  1479.         );
  1480.     }
  1481.     ulog(-1, "REQUEST FAILED -- TEMPFILE");
  1482.     return FAIL;
  1483.     }
  1484.  
  1485.     ulog(-1, "REQUEST %s", buf);
  1486.     if (wrmsg(buf) != SUCCESS) {
  1487.     fclose(fddsk);
  1488.     UnLockFile(temp);
  1489.     printf("uucico: problem sending request\n");
  1490.     return FAIL;
  1491.     }
  1492.  
  1493.     /* See what the other side has to say about it */
  1494.  
  1495.     if (rdmsg(buf, MAXMSGLEN) != SUCCESS) {
  1496.     fclose(fddsk);
  1497.     UnLockFile(temp);
  1498.     return FAIL;
  1499.     }
  1500.     if ((buf[0] != 'R') || (buf[1] != 'Y')) {
  1501.     ulog(-1, "REQUEST DENIED %s", buf);
  1502.     fclose(fddsk);
  1503.     UnLockFile(temp);
  1504.     return (REFUSED);
  1505.     }
  1506.  
  1507.     r = receive_file(fddsk, temp, dstnam, srcnam, 0);
  1508.     UnLockFile(temp);
  1509.     return(r);
  1510. }
  1511.  
  1512. /*
  1513.  *  General receive file
  1514.  */
  1515.  
  1516. int
  1517. receive_file(fddsk, temp, dstnam, srcnam, norename)
  1518. FILE *fddsk;
  1519. char    *temp, *dstnam, *srcnam;
  1520. {
  1521.     int status;
  1522.     int error = 0;            /* No errors so far */
  1523.  
  1524.     if (rddata(fddsk) != SUCCESS)
  1525.     error++;
  1526.     status = fclose(fddsk);         /* Make sure the data got here */
  1527.     if (status != 0) {
  1528.     error++;
  1529.     DEBUG(0, "fclose errno=%d\n", errno);
  1530.     }
  1531.  
  1532.     /*
  1533.      *    Move the file from its temp location to its real location,
  1534.      *    This needs to be able to copy a file if a simple rename
  1535.      *    does not suffice.  Should create directories if necesary.
  1536.      *    should use source ]name if target is a directory (i.e. no
  1537.      *    target source name
  1538.      */
  1539.  
  1540.     unlink(dstnam);
  1541.  
  1542.     if (norename)       /*  for security redirect   */
  1543.     status = 0;
  1544.     else
  1545.     status = rename(temp, dstnam);
  1546.  
  1547.     if (status != 0) {
  1548.     error++;
  1549.     if (debug > 0) {
  1550.         printf("Cannot rename file %s to %s, errno=%d\n",
  1551.         temp, dstnam, errno);
  1552.     }
  1553.     }
  1554.  
  1555.     ulog(-1, "COPY %s", error ? "FAILED": "SUCCEEDED");
  1556.  
  1557.     return(yesno('C', error == 0, 5));
  1558. }
  1559.  
  1560. /*
  1561.  * general file send routine
  1562.  * Return SUCCESS, FAIL, or COPYFAIL.
  1563.  */
  1564.  
  1565. int
  1566. send_file(fddsk)
  1567. FILE *fddsk;     /* Disk file pointer */
  1568. {
  1569.     static char ansbuf[MAXMSGLEN];
  1570.  
  1571.     if (wrdata(fddsk) != SUCCESS) {
  1572.     fclose(fddsk);
  1573.     return COPYFAIL;
  1574.     }
  1575.     fclose(fddsk);
  1576.  
  1577.     /* Await the "CY" or "CNddd" packet, and toss it. */
  1578.  
  1579.     while (1) {
  1580.     if (rdmsg(ansbuf, MAXMSGLEN) != SUCCESS)
  1581.         return COPYFAIL;
  1582.     if (ansbuf[0] != 'C') {
  1583.         DEBUG(0,"\nDidn't get 'CY' or 'CN', got %s\n", ansbuf);
  1584.         /* and loop looking for C message */
  1585.     } else if (ansbuf[1] == 'Y') {
  1586.         ulog(-1, "REQUESTED %s", ansbuf);
  1587.         return SUCCESS;
  1588.     } else {
  1589.         ulog(-1, "COPY FAILED %s", ansbuf);
  1590.         return COPYFAIL;
  1591.     }
  1592.     }
  1593.     return COPYFAIL;
  1594. }
  1595.  
  1596.